package ca.quicko.model;

import java.io.Serializable;

import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.ManyToOne;

import org.apache.commons.lang.builder.CompareToBuilder;
import org.apache.commons.lang.builder.EqualsBuilder;
import org.apache.commons.lang.builder.HashCodeBuilder;
import org.apache.commons.lang.builder.ToStringBuilder;
import org.appfuse.model.BaseObject;
import org.appfuse.model.User;
import org.hibernate.annotations.Parameter;
import org.hibernate.annotations.Type;

/**
 * Action taken by a User on a particular Issue
 * @author <a href="mailto:eric.s.landry@gmail.com">Eric S. Landry</a>
 */
@Entity
public class Act extends BaseObject implements Comparable, Serializable {
	private static final long serialVersionUID = 1773838910506577573L;

	@Id
	@GeneratedValue(strategy = GenerationType.AUTO)
	private Long id;

	/**
	 * The actor of this act. aka - the person taking action
	 */
	@ManyToOne(optional = false)
	private User user;

	/**
	 * The issue on which the person is taking action
	 */
	@ManyToOne(optional = false)
	private Issue issue;

	/**
	 * The solution proposed
	 */
	@ManyToOne(optional = false)
	private Solution solution;

	@Column(columnDefinition = "integer", nullable = false)
	@Type(type = "ca.quicko.commons.hibernate.GenericEnumUserType", parameters = {
			@Parameter(name = "enumClass", value = "ca.quicko.model.Act$Position"),
			@Parameter(name = "identifierMethod", value = "toInt"),
			@Parameter(name = "valueOfMethod", value = "fromInt") })
	private Position position;

	public Long getId() {
		return id;
	}

	public Issue getIssue() {
		return issue;
	}

	public Position getPosition() {
		return position;
	}

	public User getUser() {
		return user;
	}

	public void setId(Long id) {
		this.id = id;
	}

	public void setIssue(Issue issue) {
		this.issue = issue;
	}

	public void setPosition(Position position) {
		this.position = position;
	}

	public void setUser(User user) {
		this.user = user;
	}

	public Solution getSolution() {
		return solution;
	}

	public void setSolution(Solution solution) {
		this.solution = solution;
	}

	public Act() {
		// Entity must have a no-arg public or protected constructor
	}

	public enum Position {
		UNKNOWN(-1), FOR(1), AGAINST(2), INDIFFERENT(3);

		private int value;

		Position(int value) {
			this.value = value;
		}

		// the identifierMethod
		public int toInt() {
			return value;
		}

		// the valueOfMethod
		public static Position fromInt(int value) {
			switch (value) {
				case 1:
					return FOR;
				case 2:
					return AGAINST;
				case 3:
					return INDIFFERENT;
				default:
					return UNKNOWN;
			}
		}

		public String toString() {
			switch (this) {
				case FOR:
					return "For";
				case AGAINST:
					return "Against";
				case INDIFFERENT:
					return "Indifferent";
				default:
					return "";
			}
		}
	}

	/**
	 * @see java.lang.Comparable#compareTo(Object)
	 */
	public int compareTo(Object object) {
		Act myClass = (Act) object;
		return new CompareToBuilder().append(this.position, myClass.position)
				.append(this.id, myClass.id).append(this.issue, myClass.issue)
				.append(this.solution, myClass.solution).append(this.user,
						myClass.user).toComparison();
	}

	/**
	 * @see java.lang.Object#equals(Object)
	 */
	public boolean equals(Object object) {
		if (!(object instanceof Act)) {
			return false;
		}
		Act rhs = (Act) object;
		return new EqualsBuilder().append(this.position, rhs.position).append(
				this.id, rhs.id).append(this.issue, rhs.issue).append(
				this.solution, rhs.solution).append(this.user, rhs.user)
				.isEquals();
	}

	/**
	 * @see java.lang.Object#hashCode()
	 */
	public int hashCode() {
		return new HashCodeBuilder(-1152130117, 270712525)
				.append(this.position).append(this.id).append(this.issue)
				.append(this.solution).append(this.user).toHashCode();
	}

	/**
	 * @see java.lang.Object#toString()
	 */
	public String toString() {
		return new ToStringBuilder(this).append("issue", this.issue).append(
				"solution", this.solution).append("user", this.user).append(
				"position", this.position).append("id", this.id).toString();
	}

}
